package com.alnex.activiti.ZKdemo;

import java.util.concurrent.CountDownLatch;
import org.I0Itec.zkclient.IZkDataListener;

//功能描述:(第四步  创建实现ZK锁的子类  继承上一个的抽象类  获取锁 和等待锁两个方法)

public class ZookeeperDistrbuteLock extends AbstractZookeeperLock{

	@Override
	Boolean tryGetLock() {
		if(zkClient!=null) {
			//创建节点 如果当前节点创建成功了 就不会报异常  就返回true
			//如果创建失败了就返回 true
			try {
				zkClient.createEphemeral(PATH);
				return true;
			} catch (Exception e) {
				//走到异常里面去了 说明没有创建成功
				return false;
			}
		
		}
		return null;
	}

	@Override
	void waitGetLock() {


		//1.使用事件监听 查看当前节点是否被删除了  IZkDataListener是对节点事件（数据事件）的监听
		IZkDataListener iZkDataListener = new IZkDataListener() {
			
			//2.只监听删除事件就可以了  当节点被删除 信号量不为空 的时候 该节点信号量就--,唤醒拥有这个信号量的等待线程，
			//让他去尝试获取锁
			public void handleDataDeleted(String arg0) throws Exception {
				if(countDownLatch!=null) {
					//唤醒等待的线程
					countDownLatch.countDown();
				}
			}
			
			public void handleDataChange(String arg0, Object arg1) throws Exception {
				// TODO 不需要监听的
			}
		};
		
		//3. 将上面的监听信息注册到客户端  subscribeDataChanges  是对节点信息进行注册的
		zkClient.subscribeDataChanges(PATH,iZkDataListener);
		//4.再检测当前节点是否存在
		if(zkClient.exists(PATH)) {
			//如果当前节点已经存在了  信号量就会控制当前线程等待
			CountDownLatch countDownLatch = new CountDownLatch(1);
			try {
				//让当前信号量等待
				countDownLatch.await();
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
		//如果当前节点不存在 说明这个节点现在已经在这个线程上了获取到了,就删除这个节点的监听了
		zkClient.unsubscribeDataChanges(PATH, iZkDataListener);
		
	}

}

